package org.rain.core.storage.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import org.rain.common.exception.BaseException;
import org.rain.common.util.Ios;
import org.rain.common.util.Strs;
import org.rain.common.util.storage.F;
import org.rain.core.storage.mapper.SysFileMapper;
import org.rain.core.storage.model.entity.SysFile;
import org.rain.core.storage.service.ISysFileService;
import org.rain.core.util.RespUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * created by yangtong on 2025/4/11 22:44:42
 */
@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {

    @Override
    public void delete(String fileId) {
        if (Strs.isEmpty(fileId)) {
            return;
        }
        SysFile sysFile = getOne(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getFileId, fileId).last("limit 1"));
        if (sysFile != null) {
            F.remove(fileId);
            removeById(sysFile.getId());
        }
    }

    @Override
    public String upload(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        long fileSize = file.getSize();
        String fileSizeText = Strs.formatSize(fileSize);
        String fileType = file.getContentType();
        try (InputStream is = file.getInputStream()) {
            //上传文件
            String fileId = F.upload(is);
            //保持文件上传记录
            SysFile sysFile = new SysFile();
            sysFile.setFileId(fileId);
            sysFile.setFileName(fileName);
            sysFile.setFileSize(fileSize);
            sysFile.setFileSizeText(fileSizeText);
            sysFile.setFileType(fileType);
            sysFile.setDownloadCount(0);
            save(sysFile);

            return fileId;
        } catch (IOException e) {
            throw new BaseException(e);
        }
    }

    @Override
    public void download(String fileId) {
        SysFile sysFile = getOne(Wrappers.<SysFile>lambdaQuery().eq(SysFile::getFileId, fileId));
        if (sysFile == null) {
            throw new BaseException("文件记录不存在");
        }
        //获取文件流
        try (InputStream inputStream = F.get(fileId)) {
            HttpServletResponse resp = RespUtil.getResp();

            // 判断是否为可预览文件类型
            String fileType = sysFile.getFileType();
            String dispositionType = fileType != null && (
                    fileType.startsWith("image/") ||
                            fileType.startsWith("video/") ||
                            fileType.equals("text/plain") ||
                            fileType.equals("application/pdf")
            ) ? "inline" : "attachment";

            //设置响应头
            String encodedFileName = URLEncoder.encode(sysFile.getFileName(), StandardCharsets.UTF_8);
            resp.setHeader("Content-Disposition", dispositionType + "; filename*=UTF-8''" + encodedFileName);
            resp.setContentType(sysFile.getFileType());
            resp.setContentLengthLong(sysFile.getFileSize());
            Ios.copy(inputStream, resp.getOutputStream());

            //刷新
            resp.flushBuffer();

            update(null, Wrappers.<SysFile>lambdaUpdate()
                    .set(SysFile::getDownloadCount, sysFile.getDownloadCount() + 1)
                    .eq(SysFile::getId, sysFile.getId())
            );
        } catch (IOException e) {
            throw new BaseException(e);
        }
    }
}
